<template>
	<view class="vi_transfer">
		<!-- 上选择框 -->
		<view class="vi_transfer_upBox" :style="boxStyleUp">
			<vi-searchbar v-if="useSearch"
				:type="setting.type"
				:color="color"
				:radius="setting.radius"
				:height="searchSetting.height"
				:bgColor="searchSetting.bgColor"
				:plain="searchSetting.plain"
				:placeholder="searchSetting.placeholder"
				:buttonStyle="searchSetting.buttonStyle"
				:text="textSetting"
				@search="onSearch($event,'reserve')"></vi-searchbar>
			<scroll-view class="vi_transfer_scroll" :style="scrollStyle" scroll-y @touchmove.stop>
				<view class="vi_transfer_item" v-for="(item, index) in reserveList" :key="index" v-if="!item._hide">
					<vi-checkbox @change="onSelect($event,item)"
						:checked="item.checked"
						:type="setting.type"
						:color="color"
						:readOnly="item.readOnly||readOnly"
						:disabled="item.disabled||disabled"
						:readOnlyMsg="item.readOnlyMsg||readOnlyMsg"
						:disabledMsg="item.disabledMsg||disabledMsg">
						{{item[keySetting.name]}}
					</vi-checkbox>
				</view>
			</scroll-view>
		</view>
		<view class="vi_transfer_toolbar">
			<!-- 左按钮 -->
			<view class="vi_transfer_toolbarL">
				<view class="vi_transfer_textBtn">
					<view class="vi_transfer_textBtnbox">
						<vi-style-controller @click="onSelectAll('reserve',true)"
							control="text"
							:type="setting.type"
							:color="color"
							:disabled="reserveLen==reserveShowLen||disabled||readOnly"
							active>
							{{textSetting.selectAll}}
						</vi-style-controller>
					</view>
					<view class="vi_transfer_textBtnbox">
						<vi-style-controller @click="onSelectAll('reserve',false)"
							control="text"
							:type="setting.type"
							:color="color"
							:disabled="!reserveLen||disabled||readOnly"
							active>
							{{textSetting.clear}}
						</vi-style-controller>
					</view>
				</view>
				<view class="vi_transfer_transBtn" style="justify-self:flex-end;">
					<vi-button @click="transferDo('down')"
						:type="setting.type"
						:color="color"
						:textColor="textColor"
						width="4em"
						height="100%"
						radius="0"
						:borderWidth="0"
						:disabled="!reserveLen||disabled||readOnly">
						<text class="iconfont" :class="iconSetting.down"></text>
					</vi-button>
				</view>
			</view>
			<!-- 右按钮 -->
			<view class="vi_transfer_toolbarR">
				<view class="vi_transfer_transBtn">
					<vi-button @click="transferDo('up')"
						:type="setting.type"
						:color="color"
						:textColor="textColor"
						width="4em"
						height="100%"
						radius="0"
						:borderWidth="0"
						:disabled="!selectLen||disabled||readOnly">
						<text class="iconfont" :class="iconSetting.up"></text>
					</vi-button>
				</view>
				<view class="vi_transfer_textBtn">
					<view class="vi_transfer_textBtnbox">
						<vi-style-controller @click="onSelectAll('select',true)"
							control="text"
							:type="setting.type"
							:color="color"
							:disabled="selectLen==selectShowLen||disabled||readOnly"
							active>
							{{textSetting.selectAll}}
						</vi-style-controller>
					</view>
					<view class="vi_transfer_textBtnbox">
						<vi-style-controller @click="onSelectAll('select',false)"
							control="text"
							:type="setting.type"
							:color="color"
							:disabled="!selectLen||disabled||readOnly"
							active>
							{{textSetting.clear}}
						</vi-style-controller>
					</view>
				</view>
			</view>
		</view>
		<!-- 下选择框 -->
		<view class="vi_transfer_downBox" :style="boxStyleDown">
			<vi-searchbar v-if="useSearch"
				:type="setting.type"
				:color="color"
				:radius="setting.radius"
				:height="searchSetting.height"
				:bgColor="searchSetting.bgColor"
				:plain="searchSetting.plain"
				:placeholder="searchSetting.placeholder"
				:buttonStyle="searchSetting.buttonStyle"
				:text="textSetting"
				@search="onSearch($event,'select')"></vi-searchbar>
			<scroll-view class="vi_transfer_scroll" :style="scrollStyle" scroll-y @touchmove.stop>
				<view class="vi_transfer_item" v-for="(item, index) in selectList" :key="index" v-if="!item._hide">
					<vi-checkbox @change="onSelect($event,item)"
						:checked="item.checked"
						:type="setting.type"
						:color="color"
						:readOnly="item.readOnly||readOnly"
						:disabled="item.disabled||disabled"
						:readOnlyMsg="item.readOnlyMsg||readOnlyMsg"
						:disabledMsg="item.disabledMsg||disabledMsg">
						{{item[keySetting.name]}}
					</vi-checkbox>
				</view>
			</scroll-view>
		</view>
		<view class="vi_transfer_submitBtn" v-if="setting.useSubmit">
			<vi-button @click="submit"
				:type="setting.type"
				:color="color"
				:textColor="textColor"
				:radius="submitRadius"
				:size="submitSize"
				:plain="submitPlain"
				:width="setting.submitWidth"
				:height="submitHeight"
				:disabled="disabled"
				:readOnly="readOnly">{{textSetting.confirm}}</vi-button>
		</view>
	</view>
</template>

<script>
	export default{
		name:"",
		props:{
			//数据集
			dataList:{
				type:[Array,null],
				default:()=>[]
			},
			value:{
				type:[Array,null],
				default:()=>[]
			},
			type:{
				type:[String,null],
				default:null
			},
			color:{
				type:[String,null],
				default:""
			},
			textColor:{
				type:[String,null],
				default:""
			},
			height:{
				type:[String,null],
				default:""
			},
			radius:{
				type:[String,null],
				default:null
			},
			useSearch:{
				type:[Boolean,null],
				default:false
			},
			useSubmit:{
				type:[Boolean,null],
				default:null
			},
			submitRadius:{
				type:[String,Number,null],
				default:null
			},
			submitSize:{
				type:[String,null],
				default: null
			},
			submitPlain:{
				type:[Boolean,null],
				default:null
			},
			submitWidth:{
				type:[String,null],
				default:null
			},
			submitHeight:{
				type:[Number,String,null],
				default:null
			},
			resFormat:{
				type:[String,null],
				default:""
			},
			readOnly:{
				type:[Boolean,null],
				default:false
			},
			disabled:{
				type:[Boolean,null],
				default:false
			},
			//禁用时点击提示消息
			disabledMsg:{
				type:[String,null],
				default:""
			},
			//只读时点击提示消息
			readOnlyMsg:{
				type:[String,null],
				default:""
			},
			//搜索条设置
			searchSet:{
				type:[Object,null],
				default:()=>({})
			},
			keys:{
				type:[Object,null],
				default:()=>({})
			},
			//图标
			icon:{
				type:[Object,null],
				default:()=>({})
			},
			//文字
			text:{
				type:[Object,null],
				default:()=>({})
			}
		},
		data(){
			return {
				inList:[],				//原始数据
				reserveList:[],
				selectList:[],
				reserveLen:0,
				selectLen:0,
				reserveShowLen:0,		//显示的数据长度
				selectShowLen:0,		//显示的数据长度
				dicKeys:{
					name: "name",		//名称键名
					value: "value",		//值键名
				},
				dicIcon:{
					up: "icon-arr-double-up",
					down: "icon-arr-double-down",
				},
				dicText:{
					selectAll: "全选",
					clear: "清空",
					reset: "重置",
					confirm: "确定"
				},
				dicSearchSet:{
					open:false,
					height:2,
					bgColor:"#eee",
					plain:false,
					// placeholder:"", 使用默认
					//搜索按钮样式，可选：
					//iconLeft内部左侧图标，iconRight内部右侧图标
					//outsideLeft外部左侧按钮，outsideRight外部右侧按钮
					//insideLeft内部左侧衔接按钮，insideRight内部右侧衔接按钮
					//active动态搜索(注意性能问题)
					buttonStyle:"iconRight",
				},
			}
		},
		computed:{
			setting(){
				return {
					height: this.height ||"15em",
					radius: this.$api.isDefined(this.radius)? this.radius :"circle",
					type: this.$api.isDefined(this.type)? this.type :"primary",
					useSubmit: this.$api.isBoolean(this.useSubmit)? this.useSubmit :true,
					submitWidth: this.$api.isDefined(this.submitWidth)? this.submitWidth :"100%",
					resFormat: this.resFormat ||"value",
				}
			},
			keySetting(){
				if(this.$api.isObject(this.keys)){
					return Object.assign({},this.dicKeys,this.keys)
				}
				return this.dicKeys
			},
			searchSetting(){
				if(this.$api.isObject(this.searchSet)){
					return Object.assign({},this.dicSearchSet,this.searchSet)
				}
				return this.dicSearchSet
			},
			boxStyleUp(){
				let R = this.setting.radius;
				let res ={
					"height": this.setting.height,
					"border-radius": `${R} ${R} 0 0`
				};
				return this.$api.objToStr(res)
			},
			boxStyleDown(){
				let R = this.setting.radius;
				let res ={
					"height": this.setting.height,
					"border-radius": `0 0 ${R} ${R}`
				};
				return this.$api.objToStr(res)
			},
			scrollStyle(){
				return this.useSearch? `height:calc(100% - 2.5em);` :`height:100%;`
			},
			textSetting(){
				if(this.$api.isObject(this.text)){
					return Object.assign({},this.dicText,this.text)
				}
				return this.dicText
			},
			iconSetting(){
				if(this.$api.isObject(this.icon)){
					return Object.assign({},this.dicIcon,this.icon)
				}
				return this.dicIcon
			}
		},
		methods:{
			//初始化
			init(){
				let fromValue =false;
				//取值可从列表上提取或value赋予，value优先级更高
				if(this.value||this.value.length){
					fromValue =true
				}
				let selectList =[];
				let reserveList =[];
				for(let item of this.inList){
					if(fromValue){
						if(item.checked){
							selectList.push(item)
						}else{
							reserveList.push(item)
						}
					}else{
						reserveList.push(item)
					}
				}
				this.selectList = selectList;
				this.reserveList = reserveList;
			},
			//搜索
			onSearch(word, type){
				let list =[];
				if(type=="reserve"){
					list = this.reserveList
				}else if(type=="select"){
					list = this.selectList
				}
				for(let item of list){
					let valStr = String(item[this.keySetting.value]);
					item["_hide"] = !valStr.includes(word);
					if(item._hide){
						item.checked =false;
					}
				}
				this.computeLen();
				this.$forceUpdate();
			},
			//选择变更
			onSelect(val,item){
				item.checked = val;
				this.computeLen();
			},
			//计算选取，只计算显示的
			computeLen(type){
				let count1 =0,
					count2 =0,
					count3 =0,
					count4 =0;
				for(let item of this.reserveList){
					if(item.checked){
						count1++
					}
					if(!item._hide){
						count3++
					}
				}
				for(let item of this.selectList){
					if(item.checked){
						count2++
					}
					if(!item._hide){
						count4++
					}
				}
				this.reserveLen = count1;
				this.selectLen = count2;
				this.reserveShowLen = count3;
				this.selectShowLen = count4;
			},
			//执行穿梭
			transferDo(type){
				let reserveList = this.reserveList,
					selectList = this.selectList,
					idxList = [],
					tempList = [];
				if(type=="down"){
					for(let i=reserveList.length-1; i>=0; i--){
						let item = reserveList[i];
						if(item.checked){
							item.checked = false;
							item._hide = false;
							idxList.push(i);
						}
					}
					for(let idx of idxList){
						tempList.unshift(...reserveList.splice(idx,1));
					}
					selectList.push(...tempList);
				}else if(type=="up"){
					for(let i=selectList.length-1; i>=0; i--){
						let item = selectList[i];
						if(item.checked){
							item.checked = false;
							idxList.push(i);
						}
					}
					for(let idx of idxList){
						tempList.unshift(...selectList.splice(idx,1));
					}
					reserveList.push(...tempList);
				}
				this.computeLen();
			},
			//全选、全取消
			onSelectAll(type, val){
				let list;
				if(type=="reserve"){
					list = this.reserveList
				}else if("select"){
					list = this.selectList
				}
				for(let item of list){
					if(!item._hide){
						item.checked = val
					}
				}
				this.computeLen();
			},
			//提交
			submit(resFormat){
				this.$emit("submit", {
					select: this.getData(),
					unSelect: this.getData({type:"unSelect"})
				})
			},
			getData(options={}){
				let {type="select", resFormat=this.setting.resFormat, key} = options;
				let list;
				switch(type){
					case "select":
						list = this.selectList;
						break;
					case "unSelect":
						list = this.reserveList;
						break;
					case "all":
						list = this.inList;
						break;
				}
				switch(resFormat){
					case "value":
						return list.map((item)=>{return item[this.keySetting.value]})
					case "option":
						return list.map((item)=>{
							return {
								name:item[this.keySetting.name],
								value:item[this.keySetting.value]
							}
						})
					case "count":
						return list.length
					case "key":
						if(key&&typeof(key)=="string"){
							return list.map((item)=>{ return item[key]})
						}
						console.error("key未定义")
						return list
					default:
						return list
				}
			},
		},
		watch:{
			"dataList":{
				immediate:true,
				handler(newValue){
					this.inList = newValue ||[];
					this.init();
				}
			}
		}
	}
</script>

<style lang="scss">
$borderColor:#ddd;
.vi_transfer{
	.vi_transfer_upBox{
		padding: 0.5em 0.75em;
		border-width: 1px 1px 0 1px;
		border-style: solid;
		border-color: $borderColor;
		box-sizing: border-box;
	}
	.vi_transfer_downBox{
		padding: 0.5em 0.75em;
		border-width: 0 1px 1px 1px;
		border-style: solid;
		border-color: $borderColor;
		box-sizing: border-box;
	}
	.vi_transfer_scroll{
		width: 100%;
		margin-top: 0.5em;
	}
	.vi_transfer_item{
		padding: 0.5em 0;
	}
	.vi_transfer_toolbar{
		height: 2em;
		display: flex;
		.vi_transfer_toolbarL,
		.vi_transfer_toolbarR{
			display: flex;
		}
		.vi_transfer_toolbarL{
			flex-grow: 1;
			border-left: 1px solid $borderColor;
			border-bottom: 1px solid $borderColor;
			// border-top: 1px solid transparent;
		}
		.vi_transfer_toolbarR{
			flex-grow: 1;
			border-left: 1px solid $borderColor;
			border-right: 1px solid $borderColor;
			border-top: 1px solid $borderColor;
			// border-bottom: 1px solid transparent;
		}
		.vi_transfer_textBtn{
			display: flex;
			justify-content: center;
			align-items: center;
			flex-grow: 1;
		}
		.vi_transfer_textBtnbox{
			margin: 0 0.5em;
		}
		.vi_transfer_transBtn{
			height: 100%;
		}
	}
	.vi_transfer_submitBtn{
		margin-top: 1em;
	}
}
</style>